package com.hospital.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hospital.domain.pojo.Drug;
import com.hospital.domain.pojo.DrugPurchase;
import com.hospital.domain.pojo.DrugPurchaseItem;
import com.hospital.domain.utils.Result;
import com.hospital.mapper.DrugMapper;
import com.hospital.mapper.DrugPurchaseItemMapper;
import com.hospital.mapper.DrugPurchaseMapper;
import com.hospital.service.DrugPurchaseService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

@Service
@RequiredArgsConstructor
public class DrugPurchaseServiceImpl extends ServiceImpl<DrugPurchaseMapper, DrugPurchase> implements DrugPurchaseService {

    private final DrugPurchaseItemMapper itemMapper;
    private final DrugMapper drugMapper;
    private final com.hospital.service.OrdersService ordersService;

    @Override
    @Transactional
    public Result<Integer> createPurchase(Integer pId, List<Map<String, Object>> items) {
        if (pId == null || pId <= 0) return Result.fail("缺少患者ID");
        if (items == null || items.isEmpty()) return Result.fail("请选择药品");
        // 计算总额并校验
        BigDecimal total = BigDecimal.ZERO;
        List<DrugPurchaseItem> toSave = new ArrayList<>();
        for (Map<String, Object> it : items) {
            Integer drugId = toInt(it.get("drugId"));
            Integer quantity = toInt(it.get("quantity"));
            if (drugId == null || quantity == null || quantity <= 0) return Result.fail("药品或数量不正确");
            Drug d = drugMapper.selectById(drugId);
            if (d == null) return Result.fail("药品不存在: " + drugId);
            BigDecimal unitPrice = d.getPrice() == null ? BigDecimal.ZERO : d.getPrice();
            BigDecimal amount = unitPrice.multiply(BigDecimal.valueOf(quantity));
            total = total.add(amount);
            DrugPurchaseItem dpi = new DrugPurchaseItem(null, null, drugId, quantity, unitPrice, amount);
            toSave.add(dpi);
        }
        // 保存主单
        DrugPurchase dp = new DrugPurchase();
        dp.setPId(pId);
        dp.setTotalAmount(total);
        dp.setStatus(0);
        dp.setApplyTime(LocalDateTime.now());
        this.save(dp);
        // 保存明细
        Integer pid = dp.getPurchaseId();
        for (DrugPurchaseItem it : toSave) {
            it.setPurchaseId(pid);
            itemMapper.insert(it);
        }
        return Result.ok(pid);
    }

    @Override
    public Result<List<Map<String, Object>>> listPatientPurchases(Integer pId) {
        if (pId == null) return Result.fail("缺少患者ID");
        // 简单联表手写SQL在Mapper中也可，这里用两次查询组装
        List<DrugPurchase> list = this.lambdaQuery().eq(DrugPurchase::getPId, pId).orderByDesc(DrugPurchase::getApplyTime).list();
        List<Map<String, Object>> out = new ArrayList<>();
        for (DrugPurchase dp : list) {
            Map<String, Object> row = new LinkedHashMap<>();
            row.put("purchaseId", dp.getPurchaseId());
            row.put("totalAmount", dp.getTotalAmount());
            row.put("status", dp.getStatus());
            row.put("applyTime", dp.getApplyTime());
            row.put("approveTime", dp.getApproveTime());
            row.put("approveRemark", dp.getApproveRemark());
            // items
            List<DrugPurchaseItem> items = itemMapper.selectList(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<DrugPurchaseItem>().eq("purchaseId", dp.getPurchaseId()));
            List<Map<String, Object>> itemVO = new ArrayList<>();
            for (DrugPurchaseItem it : items) {
                Drug d = drugMapper.selectById(it.getDrugId());
                Map<String, Object> itRow = new LinkedHashMap<>();
                itRow.put("drugId", it.getDrugId());
                itRow.put("drugName", d != null ? d.getDName() : "");
                itRow.put("spec", d != null ? d.getSpec() : "");
                itRow.put("quantity", it.getQuantity());
                itRow.put("unitPrice", it.getUnitPrice());
                itRow.put("amount", it.getAmount());
                itemVO.add(itRow);
            }
            row.put("items", itemVO);
            out.add(row);
        }
        return Result.ok(out);
    }

    @Override
    public Result<List<Map<String, Object>>> listPendingPurchases() {
        List<DrugPurchase> list = this.lambdaQuery().eq(DrugPurchase::getStatus, 0).orderByAsc(DrugPurchase::getApplyTime).list();
        List<Map<String, Object>> out = new ArrayList<>();
        for (DrugPurchase dp : list) {
            Map<String, Object> row = new LinkedHashMap<>();
            row.put("purchaseId", dp.getPurchaseId());
            row.put("pId", dp.getPId());
            row.put("totalAmount", dp.getTotalAmount());
            row.put("applyTime", dp.getApplyTime());
            // items
            List<DrugPurchaseItem> items = itemMapper.selectList(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<DrugPurchaseItem>().eq("purchaseId", dp.getPurchaseId()));
            List<Map<String, Object>> itemVO = new ArrayList<>();
            for (DrugPurchaseItem it : items) {
                Drug d = drugMapper.selectById(it.getDrugId());
                Map<String, Object> itRow = new LinkedHashMap<>();
                itRow.put("drugId", it.getDrugId());
                itRow.put("drugName", d != null ? d.getDName() : "");
                itRow.put("spec", d != null ? d.getSpec() : "");
                itRow.put("quantity", it.getQuantity());
                itRow.put("unitPrice", it.getUnitPrice());
                itRow.put("amount", it.getAmount());
                itemVO.add(itRow);
            }
            row.put("items", itemVO);
            out.add(row);
        }
        return Result.ok(out);
    }

    @Override
    @Transactional
    public Result<Void> approve(Integer purchaseId, Integer approverId, Integer approverRole, String remark, boolean pass) {
        DrugPurchase dp = this.getById(purchaseId);
        if (dp == null) return Result.fail("申请不存在");
        if (dp.getStatus() != null && dp.getStatus() != 0) return Result.fail("已处理");
        dp.setStatus(pass ? 1 : 2);
        dp.setApproveTime(LocalDateTime.now());
        dp.setApproverId(approverId);
        dp.setApproverRole(approverRole);
        dp.setApproveRemark(remark);
        this.updateById(dp);
        if (pass) {
            // 扣减库存
            List<DrugPurchaseItem> items = itemMapper.selectList(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<DrugPurchaseItem>().eq("purchaseId", purchaseId));
            for (DrugPurchaseItem it : items) {
                Drug d = drugMapper.selectById(it.getDrugId());
                if (d != null) {
                    int newStock = (d.getStock() == null ? 0 : d.getStock()) - (it.getQuantity() == null ? 0 : it.getQuantity());
                    if (newStock < 0) newStock = 0; // 不允许负库存
                    d.setStock(newStock);
                    drugMapper.updateById(d);
                }
            }
            // 创建购药订单：标题为若干药品x数量，金额为总额
            try {
                StringBuilder title = new StringBuilder();
                for (int i = 0; i < items.size(); i++) {
                    DrugPurchaseItem it = items.get(i);
                    Drug d = drugMapper.selectById(it.getDrugId());
                    String name = d != null ? d.getDName() : ("药品" + it.getDrugId());
                    if (i > 0) title.append(", ");
                    title.append(name).append("x").append(it.getQuantity());
                    if (title.length() > 200) { title.append("..."); break; }
                }
                ordersService.createDrugOrder(dp.getPId(), purchaseId, title.toString(), dp.getTotalAmount());
            } catch (Exception ignored) {}
        }
        return Result.ok();
    }

    private Integer toInt(Object o) {
        if (o == null) return null;
        if (o instanceof Number) return ((Number) o).intValue();
        try { return Integer.parseInt(String.valueOf(o)); } catch (Exception e) { return null; }
    }
}

